*** Settings ***
Library           Collections
Library           String
Library           RequestsLibrary
Library           json
Library           ZookeeperLibrary
Library           DatabaseLibrary
Library           XML
Library           JSONLibrary
Library           migu_library

*** Keywords ***
获取请求报文
    [Arguments]    ${Req_Data_File}    ${Random_Element}    @{Req_Data_Num}
    [Documentation]    用于从配置文件获取单条或多条请求报文，返回报文list
    ...
    ...    入参说明：
    ...
    ...    ${reqDataFile} 接口报文配置文件.conf后缀，使用工程相对路径，例如TestCases\\点播\\执行类接口\\余额鉴权.conf，引用测试套变量${Req_Data_File}。
    ...
    ...    ${randomElement} 报文里需要被替换成随机数的字段，
    ...    例如报文里的ORDER_ID需要替换成22位的随机数，ProcessTime需要替换成14位的随机数，变量值为
    ...    {"ORDER_ID":"0000000000000000000000-9999999999999999999999","ProcessTime":"2017000000000-20179999999999"}，报文配置文件里的字段值需要写成变量的形式：${ORDER_ID}，${ProcessTime}。
    ...
    ...    @{Req_Data_Num} 报文配置文件里的报文编号，例如Req_Data_01，可以同时指定多个。
    ...
    ...    出参说明：
    ...
    ...    ${req_data_list} 返回的请求报文list
    ...
    ...    ${randomvalue} 请求报文里替换的随机数的值，例如：{"ORDER_ID":"92345678912345643213456","ProcessTime":"20171234543445"}
    ...
    ...    示例：
    ...
    ...    | ${req_data_list} | ${randomvalue} | 获取请求报文 | ${Req_Data_File} | ${Random_Element} | Req_Data_01 | Req_Data_02 |
    ...
    ...    | ${req_data_list} | 获取请求报文 | ${Req_Data_File} | ${randomvalue} | Req_Data_001 |
    ...
    ...    返回结果引用示例：
    ...
    ...    | ${responsedata} | 发送请求报文 | ${G_OrderUrl} | post | xml | @{req_data_list}[0] |
    ${req_data_list}    ${randomElementValue}    migu_library.Get Req Data List    ${Req_Data_File}    ${Random_Element}    @{Req_Data_Num}
    [Return]    ${req_data_list}    ${randomElementValue}

发送Get请求
    [Arguments]    ${URL}    ${URI}    ${params}=${None}    ${headers}=${None}    ${data}=${None}    ${allow_redirects}=${None}
    ...    ${timeout}=${None}
    [Documentation]    用于向服务器发送Get请求，返回服务器响应报文。
    ...
    ...    入参说明：
    ...
    ...    ${URL}：服务器URL地址
    ...
    ...    ${URI}：服务器资源标识符
    ...
    ...    ${params}：URL参数
    ...
    ...    ${headers}：消息头
    ...
    ...
    ...    示例：
    ...
    ...    | ${requestDataList} | ${randomElementValue} | 获取请求报文 | ${Req_Data_File} | ${Random_Element} | Req_Data_001 |
    ...    | ${response} | 发送Get请求 | http://172.30.150.144:8101 \ | \ /order/payinfobackfill \ | params=@{requestDataList}[0] |
    ...    | ${URL} | Get Json Value | ${response} | /url |
    Create Session    API    ${URL}
    Comment    ${params}    Run Keyword If    '''${params}'''=='''${None}'''    Set Variable    ${params}
    ...    ELSE    JsonToDict    ${params}
    ${response}    Get Request    API    ${URI}    headers=${headers}    params=${params}    data=${data}
    ...    allow_redirects=${allow_redirects}    timeout=${timeout}
    [Return]    ${response}

发送Post请求
    [Arguments]    ${URL}    ${URI}    ${data}=${None}    ${headers}=${None}    ${params}=${None}    ${files}=${None}
    ...    ${allow_redirects}=${None}    ${timeout}=${None}
    [Documentation]    用于向服务器发送Post请求，返回服务器响应报文。
    ...
    ...    入参说明：
    ...
    ...    ${URL}：服务器URL地址
    ...
    ...    ${URI}：服务器资源标识符
    ...
    ...    ${data}：请求数据
    ...
    ...    ${params}：URL参数
    ...
    ...    ${headers}：消息头
    ...
    ...
    ...    示例：
    ...
    ...    | ${requestDataList} | ${randomElementValue} | 获取请求报文 | ${Req_Data_File} | ${Random_Element} | Req_Data_001 |
    ...    | ${response} | 发送Post请求 | http://172.30.150.144:8101 \ | \ /order/payinfobackfill \ | data=@{requestDataList}[0] | headers=&{Headers} |
    ...    | ${URL} | Get Json Value | ${response} | /url |
    Create Session    API    ${URL}
    Comment    ${params}    Run Keyword If    '''${params}'''=='''${None}'''    Set Variable    ${params}
    ...    ELSE    JsonToDict    ${params}
    Comment    ${files}    Run Keyword If    '''${files}'''=='''${None}'''    Set Variable    ${files}
    ...    ELSE    JsonToDict    ${files}
    ${response}    Post Request    API    ${URI}    data=${data}    params=${params}    headers=${headers}
    ...    files=${files}    allow_redirects=${allow_redirects}    timeout=${timeout}
    [Return]    ${response}

发送Put请求
    [Arguments]    ${URL}    ${URI}    ${data}=${None}    ${headers}=${None}    ${params}=${None}    ${files}=${None}
    ...    ${allow_redirects}=${None}    ${timeout}=${None}
    [Documentation]    用于向服务器发送Put请求，返回服务器响应报文。
    ...
    ...    入参说明：
    ...
    ...    ${URL}：服务器URL地址
    ...
    ...    ${URI}：服务器资源标识符
    ...
    ...    ${data}：请求数据
    ...
    ...    ${params}：报文体
    ...
    ...    ${headers}：消息头
    ...
    ...
    ...    示例：
    ...
    ...    | ${requestDataList} | ${randomElementValue} | 获取请求报文 | ${Req_Data_File} | ${Random_Element} | Req_Data_001 |
    ...    | ${response} | 发送Put请求 | http://172.30.150.144:8101 \ | \ /order/payinfobackfill | data=@{requestDataList}[0] | headers=&{Headers} |
    ...    | ${URL} | Get Json Value | ${response} | /url |
    Create Session    API    ${URL}
    Comment    ${params}    Run Keyword If    '''${params}'''=='''${None}'''    Set Variable    ${params}
    ...    ELSE    JsonToDict    ${params}
    Comment    ${files}    Run Keyword If    '''${files}'''=='''${None}'''    Set Variable    ${files}
    ...    ELSE    JsonToDict    ${files}
    ${response}    Put Request    API    ${URI}    data=${data}    params=${params}    headers=${headers}
    ...    files=${files}    allow_redirects=${allow_redirects}    timeout=${timeout}
    [Return]    ${response}

发送Delete请求
    [Arguments]    ${URL}    ${URI}    ${data}=${None}    ${headers}=${None}    ${params}=${None}    ${allow_redirects}=${None}
    ...    ${timeout}=${None}
    [Documentation]    用于向服务器发送Delete请求，返回服务器响应报文。
    ...
    ...    入参说明：
    ...
    ...    ${URL}：服务器URL地址
    ...
    ...    ${URI}：服务器资源标识符
    ...
    ...    ${data}：请求数据
    ...
    ...    ${params}：URL参数
    ...
    ...    ${headers}：消息头
    ...
    ...
    ...    示例：
    ...
    ...    | ${requestDataList} | ${randomElementValue} | 获取请求报文 | ${Req_Data_File} | ${Random_Element} | Req_Data_001 |
    ...    | ${response} | 发送Delete请求 | http://172.30.150.144:8101 \ | \ /order/payinfobackfill | data=@{requestDataList}[0] | headers=&{Headers} |
    ...    | ${URL} | Get Json Value | ${response} | /url |
    Create Session    API    ${URL}
    Comment    ${params}    Run Keyword If    '''${params}'''=='''${None}'''    Set Variable    ${params}
    ...    ELSE    JsonToDict    ${params}
    ${response}    Delete Request    API    ${URI}    data=${data}    params=${params}    headers=${headers}
    ...    allow_redirects=${allow_redirects}    timeout=${timeout}
    [Return]    ${response}

发送Patch请求
    [Arguments]    ${URL}    ${URI}    ${data}=${None}    ${headers}=${None}    ${params}=${None}    ${files}=${None}
    ...    ${allow_redirects}=${None}    ${timeout}=${None}
    [Documentation]    用于向服务器发送Patch请求，返回服务器响应报文。
    ...
    ...    入参说明：
    ...
    ...    ${URL}：服务器URL地址
    ...
    ...    ${URI}：服务器资源标识符
    ...
    ...    ${data}：请求数据
    ...
    ...    ${params}：URL参数
    ...
    ...    ${headers}：消息头
    ...
    ...
    ...    示例：
    ...
    ...    | ${requestDataList} | ${randomElementValue} | 获取请求报文 | ${Req_Data_File} | ${Random_Element} | Req_Data_001 |
    ...    | ${response} | 发送Patch请求 | http://172.30.150.144:8101 \ | \ /order/payinfobackfill | data=@{requestDataList}[0] | headers=&{Headers} |
    ...    | ${URL} | Get Json Value | ${response} | /url |
    Create Session    API    ${URL}
    Comment    ${params}    Run Keyword If    '''${params}'''=='''${None}'''    Set Variable    ${params}
    ...    ELSE    JsonToDict    ${params}
    Comment    ${files}    Run Keyword If    '''${files}'''=='''${None}'''    Set Variable    ${files}
    ...    ELSE    JsonToDict    ${files}
    ${response}    Patch Request    API    ${URI}    data=${data}    params=${params}    headers=${headers}
    ...    files=${files}    allow_redirects=${allow_redirects}    timeout=${timeout}
    [Return]    ${response}

响应报文校验
    [Arguments]    ${response}    @{expect}
    [Documentation]    用于校验Json或xml响应报文与预期结果是否一致。
    ...
    ...    入参说明：
    ...
    ...    ${response}：响应报文，支持Json和XML两种格式。
    ...
    ...    @{expect}：预期结果，通过JsonPath传递待校验内容，支持==、!==、IN、Not IN 四种运算符，例如$.code == 200。
    ...
    ...    支持同时校验多个内容。
    ...
    ...    出参说明：无
    ...
    ...    示例：
    ...
    ...    | 响应报文校验 | ${response.text} | $.code == 200 | $.message !== 失败 | 成功 IN $.msg |
    : FOR    ${ret}    IN    @{expect}
    \    Response_Data_Validate    ${response}    ${ret}

响应头校验
    [Arguments]    ${responseHeaders}    @{expect}
    [Documentation]    用于校验Http请求的响应头与预期结果是否一致。
    ...
    ...    入参说明：
    ...
    ...    ${responseHeaders}：响应头，通过${response.headers}传入。
    ...
    ...    @{expect}：预期结果，通过JsonPath传递待校验内容，支持==、!==、IN、Not IN 四种运算符，例如$.Content-Type == "application/json;charset=utf-8" 或 8080 IN $.Server
    ...
    ...    支持同时校验多个内容。
    ...
    ...    出参说明：无
    ...
    ...    示例：
    ...
    ...    | 响应头校验 | ${response.headers} | $.Content-Type == "application/json;charset=utf-8" | 8080 IN $.Server |
    ${responseHeaders}    Create Dictionary    &{responseHeaders}
    ${responseHeaders}    json.dumps    ${responseHeaders}
    : FOR    ${ret}    IN    @{expect}
    \    Response_Data_Validate    ${responseHeaders}    ${ret}

响应状态码校验
    [Arguments]    @{expect}
    [Documentation]    用于校验Http请求响应状态码与预期结果是否一致。
    ...
    ...    入参说明：
    ...
    ...    @{expect}：响应状态码及预期结果表达式，支持==、!==、IN、Not IN 四种运算符，例如${response.status_code} == 200。
    ...
    ...    支持同时校验多个。
    ...
    ...    出参说明：无
    ...
    ...    示例：
    ...
    ...    | 响应状态码校验 | ${response.status_code} == 200 |
    : FOR    ${ret}    IN    @{expect}
    \    Response_StatusCode_Validate    ${ret}

状态码校验
    [Arguments]    ${status_code}    ${expect}
    [Documentation]    用于校验http请求的响应状态码是否和预期结果一致。
    ...
    ...    入参说明：
    ...
    ...    ${status_code}：状态码。
    ...
    ...    ${expect}：预期结果。
    ...
    ...    出参说明：无
    ...
    ...    示例：
    ...
    ...    | 状态码校验 | ${response.status_code} | 200 |
    Should Be Equal As Integers    ${status_code}    ${expect}

执行SQL语句
    [Arguments]    ${DBConnStr}    ${sqlStatement}    ${DBType}=pymysql
    [Documentation]    用于执行指定的SQL语句。
    ...
    ...    入参说明：
    ...
    ...    ${DBConnStr}：数据库连接串，例如username/passwd@127.0.0.1:1521/orcl
    ...
    ...    ${sqlStatement}：要执行的SQL语句，例如DELETE FROM person_employee_table
    ...
    ...    ${DBType}：数据库类型，默认值是cx_Oracle，也支持其他类型的数据库，例如mysql
    ...
    ...    示例：
    ...
    ...    | 执行SQL语句 | ${DBConnStr} | DELETE FROM person_employee_table | mysql |
    ...
    ...    | 执行SQL语句 | ${DBConnStr} | DELETE FROM person_employee_table; DELETE FROM person_table |
    Connect To Database Using Custom Params    ${DBType}    ${DBConnStr}
    Execute Sql String    ${sqlStatement}
    Disconnect From Database

获取报文字段值
    [Arguments]    ${responseData}    ${element}    ${format}=json
    [Documentation]    用于从JSON或XML格式的报文里获取指定节点的值。
    ...
    ...    入参说明：
    ...
    ...    ${responseData}：报文内容
    ...
    ...    ${element}：节点路径，有两种用法。老用法：${element}
    ...    使用类似Response/Body/ChannelId的格式描述路径，返回报文中指定节点的值。
    ...
    ...    新用法：${element}使用jsonpath语法描述节点路径，例如$.ChargeResponse.Body.TradeSession,$.ChargeResponse.Body.Code，多个使用逗号分隔。
    ...    返回jsonpath指定的节点和节点值构成的字典，例如{"Code":"200", "TradeSession":"xxxxxxxxxxxxxxx"}
    ...
    ...    ${format}：报文格式，xml 或 json，默认是json
    ...
    ...    出参说明：
    ...
    ...    返回字段值或字段名与字段值构成的字典。
    ...
    ...    示例：
    ...
    ...    | ${value} | 获取报文字段值 | ${responseData} | ChargeResponse/Body/TradeSession |
    ...
    ...    | &{value} | 获取报文字段值 | ${responseData} | $.ChargeResponse.Body.TradeSession,$.ChargeResponse.Body.Code |
    ${elementValue}    Get Response Data Value    ${responseData}    ${element}    ${format}
    [Return]    ${elementValue}

更新报文数据
    [Arguments]    ${requestdata}    @{fieldList}
    [Documentation]    用于更新Json或者XML报文指定字段的值。
    ...
    ...    入参说明：
    ...
    ...    ${requestdata}：Json或XML格式的字符串
    ...
    ...    @{fieldList}：兼容两种用法。
    ...
    ...    老用法：@{fieldList}使用JsonPath语法描述的字符串，中间使用逗号分隔，例如$.appId:100,$.userId:10001，表示将报文中的appId替换为100，userId替换为10001。
    ...
    ...    新用法：@{fieldList}可以同时输入多个key:value的内容，表示将报文中的${key}直接替换为value.
    ...
    ...    出参说明：
    ...
    ...    ${requestdata}：更新后的报文
    ...
    ...    示例：
    ...
    ...    老用法：
    ...
    ...    | ${requestData} | 更新报文数据 | ${requestDataList[0]} | $.appId:100,$.userId:10001 |
    ...
    ...    新用法：
    ...
    ...    | ${requestData} | 更新报文数据 | ${requestDataList[0]} | appId:${appId} | userId:${userId} |
    ${requestdata}    Update_Req_Data    ${requestdata}    @{fieldList}
    [Return]    ${requestdata}

更新请求头
    [Arguments]    ${expect}    &{headers}
    [Documentation]    根据指定的字典项更新请求头内容。
    ...
    ...    入参说明：
    ...
    ...    ${expect}: 需要更新的内容
    ...
    ...    &{headers}: 初始请求头
    ...
    ...    出参说明：
    ...
    ...    &{headers}：返回更新后的请求头
    ...
    ...    示例：
    ...
    ...    | &{G_Headers} | 更新请求头 | {"user-sessionId":"&{var}[sessionId]"} | &{G_Headers} |
    ${expect}    To Json    ${expect}
    @{keys}    Get Dictionary Keys    ${expect}
    : FOR    ${key}    IN    @{keys}
    \    ${value}    Get From Dictionary    ${expect}    ${key}
    \    Set To Dictionary    ${headers}    ${key}    ${value}
    [Return]    &{headers}

更新XML报文数据
    [Arguments]    ${requestdata}    ${fields}
    [Documentation]    用于更新xml报文指定字段的值。
    ...
    ...    入参说明：
    ...
    ...    ${requestdata}：xml格式的报文
    ...
    ...    ${fields}：xpath语法格式的字符串，例如html/p:111，表示将xml中html对象的子对象p的值改为111
    ...    ，如需要同时修改两个及以上，可以使用逗号分隔，如html/p:111,first:222
    ...
    ...    出参说明：
    ...
    ...    ${requestdata}：更新后的xml报文
    ...
    ...    示例：
    ...
    ...    | ${requestData} | 更新XML报文数据 | ${requestDataList[0]} | html/p:111,first:222 |
    @{fieldList}    Split String    ${fields}    ,
    : FOR    ${field}    IN    @{fieldList}
    \    ${key}    ${value}    Split String    ${field}    :
    \    ${requestdata}    Set Element Text    ${requestdata}    text=${value}    xpath=${key}
    ${requestdata}    Element To String    ${requestdata}
    ${requestdata}    Set Variable    <?xml version='1.0' encoding='UTF-8'?>${requestdata}
    [Return]    ${requestdata}

发送请求报文
    [Arguments]    ${serverUrl}    ${method}    ${dataformat}    @{requestData}
    [Documentation]    用于向服务器发送http请求报文，支持post和get两种请求，支持xml和json两种报文格式，返回服务器响应报文。
    ...
    ...    入参说明：
    ...
    ...    ${serverUrl}：服务器URL地址
    ...
    ...    ${method}：http方法，get或post
    ...
    ...    ${dataformat}：数据格式，json或xml
    ...
    ...    @{requestData}：请求报文，支持单个请求报文或者报文header和body分开两种格式。
    ...
    ...    示例：
    ...
    ...    | ${responsedata} | 发送请求报文 | ${G_OrderUrl} | post | xml | @{req_data_list}[0] |
    ${responseData}    CommonLibrary HttpInterface SendRequest    ${serverUrl}    ${method}    ${dataformat}    @{requestData}
    [Return]    ${responseData}

接口调用模板
    [Arguments]    ${serverUrl}    ${reqDataFile}    ${reqDataNum}    ${randomElement}
    [Documentation]    用于向服务器发送xml格式的POST请求。
    ...
    ...    入参说明：
    ...
    ...    ${serverUrl} 服务器URL地址，建议引用全局变量。
    ...
    ...    ${reqDataFile} 接口报文配置文件.conf后缀，使用全局变量+相对路径，例如${G_Path}\\计费\\TestCases\\点播\\计费请求接口.conf，引用测试套变量${Req_Data_File}。
    ...
    ...    ${reqDataNum} 接口报文配置文件里的报文编号，例如Req_Data_01
    ...
    ...    ${randomElement} 报文里需要被替换成随机数的字段，
    ...    例如报文里的ORDER_ID需要替换成22位的随机数，ProcessTime需要替换成14位的随机数，变量值为
    ...    {"ORDER_ID":"0000000000000000000000-9999999999999999999999","ProcessTime":"2017000000000-20179999999999"}，报文配置文件里的字段值需要写成变量的形式：${ORDER_ID}，${ProcessTime}。
    ...
    ...    返回结果说明：
    ...
    ...    ${responseData} ：服务器响应报文。
    ...
    ...    ${randomElementValue} ：报文里被替换的随机数字段，格式与入参${randomElement} 一致，例如{"ORDER_ID":"2345654321678943456786","ProcessTime":"20171234675325"}
    ...
    ...    示例：
    ...
    ...    | ${responseData} | ${randomElementValue} | 接口调用模板 | ${G_OrderUrl} | ${Req_Data_File} | Req_Data_01 | ${Random_Element} |
    #获取接口入参
    ${requestData}    ${randomElementValue}    migu_library.Get Req Data    ${reqDataFile}    ${reqDataNum}    ${randomElement}
    #调用接口
    ${responseData}    CommonLibrary HttpInterface Post Xml    ${serverUrl}    ${requestData}
    [Return]    ${responseData}    ${randomElementValue}

结果校验模板
    [Arguments]    ${responseData}    ${expectResult}    ${DBConnStr}    ${sqlStatement}=None    ${retry}=0    ${interval}=0
    ...    ${DBType}=cx_Oracle
    [Documentation]    用于xml格式响应报文的结果校验。
    ...
    ...    入参说明：
    ...
    ...    ${responseData} 接口返回结果，xml格式。
    ...
    ...    ${expectResult} 接口返回值的预期结果，字典格式，字典的key需要写清xml节点的路径，例如{"responseData/Body/resCode":"000000","responseData/Body/resDesc":"SUCCESS"}
    ...
    ...    ${DBConnStr} 数据库连接串，例如username/passwd@127.0.0.1:1521/oracle，如果不需要做数据库校验，输入None
    ...
    ...    ${sqlStatement} 数据库查询SQL语句及预期结果，字典格式，例如{"select username from table where userid='001'":"[['tom']]"}如果不需要做数据库校验，输入None
    ...
    ...    ${retry}：数据库校验最大重试时长或最大重试次数，默认时间0
    ...
    ...    ${interval}：数据库校验重试时间间隔，默认时间0
    ...
    ...    ${DBType}：数据库类型，默认值是cx_Oracle，也支持其他类型的数据库，例如mysql
    ...
    ...    示例（不需要进行数据库校验的）：
    ...
    ...    | 结果校验模板 | ${responseData} | {"GPay/Header/RspCode":"020A00"} | None | None |
    ...
    ...    示例（需要进行数据库校验且需要重试）：
    ...
    ...    | 结果校验模板 | ${responseData} | {"GPay/Header/RspCode":"020A00"} | ${G_DBConnStrMiguJF} | {"select t1.contentid from TG_FULL_CHARGE_TMP t1 where order_id = '&{randomvalue}[ORDER_ID]' union all select t2.contentid from TG_FULL_CHARGE_his_07 t2 where order_id = '&{randomvalue}[ORDER_ID]'":"[('3001230123012301203')]"} | 5min | 30s |
    ...
    ...    示例（需要进行数据库校验不需要重试）：
    ...
    ...    | 结果校验模板 | ${responseData} | {"GPay/Header/RspCode":"020A00"} | ${G_DBConnStrMiguJF} | {"select t1.contentid from TG_FULL_CHARGE_TMP t1 where order_id = '&{randomvalue}[ORDER_ID]' union all select t2.contentid from TG_FULL_CHARGE_his_07 t2 where order_id = '&{randomvalue}[ORDER_ID]'":"[('3001230123012301203')]"} |
    #接口返回结果处理
    ${responseDic}    CommonLibrary XmlStr To Dic    ${responseData}
    #接口返回结果校验
    Response Data Verify    ${responseDic}    ${expectResult}
    #数据库校验
    Run Keyword If    ${DBConnStr}!=None    数据库动态校验    ${DBConnStr}    ${sqlStatement}    ${retry}    ${interval}
    ...    ${DBType}

获取报文字段值序列
    [Arguments]    ${responseData}    ${format}    @{elementList}
    [Documentation]    用于从XML或JSON格式的报文里获取指定节点的值，返回由节点值构成的List
    ...
    ...    入参说明：
    ...
    ...    ${responseData}：报文内容
    ...
    ...    ${format}：报文格式，xml 或 json，默认是xml
    ...
    ...    @{elementList}：节点List
    ...
    ...    示例：
    ...
    ...    | @{valueList} | 获取报文字段值序列 | ${responseData} | json | ChargeResponse/Body/TradeSession | ChargeResponse/Body/Order_ID |
    ...
    ...    | @{valueList} | 获取报文字段值序列 | ${responseData} | xml | ChargeResponse/Body/TradeSession | ChargeResponse/Body/Order_ID |
    ...
    ...    通过 @{valueList}[0] 和 @{valueList}[1] 可以分别引用到报文里 TradeSession 和 Order_ID 字段的值。
    #获取指定节点的value
    ${elementValueList}    Create List
    : FOR    ${element}    IN    @{elementList}
    \    ${elementValue}    Get Response Data Value    ${responseData}    ${element}    ${format}
    \    Append To List    ${elementValueList}    ${elementValue}
    [Return]    ${elementValueList}

获取Json报文字段值
    [Arguments]    ${responseData}    ${element}
    [Documentation]    用于从JSON格式的字符串里获取指定节点的值。
    ...
    ...    入参说明：
    ...
    ...    ${responseData}：报文内容
    ...
    ...    ${element}：JsonPath语法写的节点路径，如$.playRate，如需同时获取多个字段值，可以使用逗号隔开，如$.playRate,$.rateFee
    ...
    ...    出参说明：
    ...
    ...    &{elementValue}：获取的节点值构成的dictionary
    ...
    ...    示例：
    ...
    ...    | &{value} | 获取Json报文字段值 | ${responseData} | $.playRatePlanList[0].rateFee,$.playRatePlanList[0].contentCode |
    ...    | log | &{value}[rateFee] |
    ...    | log | &{value}[contentCode] |
    ...
    ...    注意：由于关键字返回结果是个Dictronary，如需要引用其中的值，请使用&{value}[key]的方式。
    ${responseDict}    To Json    ${responseData}
    @{elementList}    Split String    ${element}    ,
    ${elementValue}    Create Dictionary
    : FOR    ${key}    IN    @{elementList}
    \    ${Value}    Get Value From Json    ${responseDict}    ${key}
    \    ${keyName}    Fetch From Right    ${key}    .
    \    Set To Dictionary    ${elementValue}    ${keyName}=${Value[0]}
    [Return]    &{elementValue}

获取XML报文字段值
    [Arguments]    ${XML}    ${element}
    [Documentation]    用于从XML格式的字符串里获取指定对象的值。
    ...
    ...    入参说明：
    ...
    ...    ${XML}：xml报文内容
    ...
    ...    ${element}：XPath语法写的节点路径，如html/p，如需同时获取多个对象的值，可以使用逗号分隔，如html/p,first
    ...
    ...    出参说明：
    ...
    ...    ${elementValue}：获取的对象值构成的list
    ...
    ...    示例：
    ...
    ...    | ${value} | 获取XML报文字段值 | <example><first id="1">this is first value</first><second id="2"><child/></second><third><child>more text</child><second id="child"/><child><grandchild/></child></third><html><p>Text with <b>bold</b> and <i>italics</i>.</p></html></example> | html/p,first |
    ...    | log | ${value[0]} |
    ...
    ...    注意：由于关键字返回结果是个List，如需要引用其中的值，请使用${value[0]}的方式。
    @{elementList}    Split String    ${element}    ,
    ${elementValue}    Create List
    : FOR    ${key}    IN    @{elementList}
    \    ${value}    Get Element Text    ${XML}    ${key}
    \    Append To List    ${elementValue}    ${value}
    [Return]    ${elementValue}

数据库校验含中文
    [Arguments]    ${DBConnStr}    ${sqlStatement}    @{expectvalue}
    [Documentation]    用于数据库校验，默认是Oracle数据库
    ...
    ...    入参说明：
    ...
    ...    ${DBConnStr}：数据库连接串，例如username/passwd@127.0.0.1:1521/orcl
    ...
    ...    ${sqlStatement}：数据库查询SQL语句
    ...
    ...    @{expectvalue}：数据库字段值预期结果，支持同时校验多个字段
    ...
    ...    示例：
    ...
    ...    | 数据库校验含中文 | db='content_center', user='migudb2', passwd='migu123', host='172.30.150.143', port=3506,use_unicode=False,charset='utf8' | SELECT content_name, content_code FROM ct_info WHERE content_id='${contentCode}' | 动漫 | 1020120000 |
    #数据库校验
    Connect To Database Using Custom Params    pymysql    ${DBConnStr}
    ${DBValue}    Query    ${sqlStatement}
    ${count}    Get Length    ${expectvalue}
    : FOR    ${i}    IN RANGE    0    ${count}
    \    ${value1}    Evaluate    '${DBValue[0][${i}]}'.decode('utf-8')
    \    ${value2}    Set Variable    @{expectvalue}[${i}]
    \    Should Be Equal As Strings    ${value1}    ${value2}
    Log    ExpectValue is the same with DB QueryValue
    Disconnect From Database

Redis集群key值校验
    [Arguments]    ${host}    ${port}    ${key}    @{contents}
    [Documentation]    用于校验Redis集群数据库某个key的值是否包含指定的内容。
    ...
    ...    入参说明：
    ...
    ...    ${host}：集群数据库某个节点的IP地址
    ...
    ...    ${port}：集群数据库某个节点的端口
    ...
    ...    ${key}：集群数据库的key
    ...
    ...    @{contents}：集群数据库key值需要包含的内容，支持同时匹配多个
    ...
    ...    示例：
    ...
    ...    | Redis集群key值校验 | 10.25.212.22 | 6101 | keys | 201705 | 10 |
    [Timeout]
    ${data}    Get From Redis Cluster    ${host}    ${port}    ${key}
    : FOR    ${content}    IN    @{contents}
    \    Should Contain    ${data}    ${content}

Redis集群哈希表字段值校验
    [Arguments]    ${host}    ${port}    ${key}    ${field}    @{contents}
    [Documentation]    用于校验Redis集群数据库某个key的表字段值是否包含指定的内容。
    ...
    ...    入参说明：
    ...
    ...    ${host}：集群数据库某个节点的IP地址
    ...
    ...    ${port}：集群数据库某个节点的端口
    ...
    ...    ${key}：集群数据库的key
    ...
    ...    ${field}：集群数据库的表字段名称
    ...
    ...    @{contents}：集群数据库key值需要包含的内容，支持同时匹配多个
    ...
    ...    示例：
    ...
    ...    | Redis集群哈希值校验 | 10.25.212.22 | 6101 | keys | field |201705 | 10 |
    [Timeout]
    ${data}    Hget From Redis Cluster    ${host}    ${port}    ${key}    ${field}
    : FOR    ${content}    IN    @{contents}
    \    Should Contain    ${data}    ${content}

Redis集群哈希表字段校验
    [Arguments]    ${host}    ${port}    ${key}    @{contents}
    [Documentation]    用于校验Redis集群数据库某个key的值是否包含指定的内容。
    ...
    ...    入参说明：
    ...
    ...    ${host}：集群数据库某个节点的IP地址
    ...
    ...    ${port}：集群数据库某个节点的端口
    ...
    ...    ${key}：集群数据库的key
    ...
    ...    @{contents}：集群数据库key值需要包含的内容，支持同时匹配多个
    ...
    ...    示例：
    ...
    ...    | Redis集群哈希表字段校验 | 10.25.212.22 | 6101 | keys | 201705 | 10 |
    [Timeout]
    ${data}    Hkeys From Redis Cluster    ${host}    ${port}    ${key}
    ${data_str}    Convert to string    ${data}
    : FOR    ${content}    IN    @{contents}
    \    Should Contain    ${data_str}    ${content}

Zookeeper节点值校验
    [Arguments]    ${hosts}    ${node}    @{expect}
    [Documentation]    用于校验zookeeper某个节点的值是否包含指定的内容。
    ...
    ...    入参说明：
    ...
    ...    ${hosts}：zookeeper服务器信息
    ...
    ...    ${node}：zookeeper节点路径
    ...
    ...    @{expect}：节点值预期包含的内容
    ...
    ...
    ...    示例：
    ...
    ...    | Zookeeper节点值校验 | 10.124.2.35:2181 | /migu/param/provStatus | <prov>891</prov> | <prov>931</prov> | <prov>951</prov> |
    Connect To Zookeeper    ${hosts}
    ${result}    Get Value    ${node}
    : FOR    ${value}    IN    @{expect}
    \    Should Contain    ${result}    ${value}
    Disconnect From Zookeeper

Zookeeper节点存在性
    [Arguments]    ${hosts}    ${node}
    [Documentation]    用于校验zookeeper某个节点是否存在。
    ...
    ...    入参说明：
    ...
    ...    ${hosts}：zookeeper服务器信息
    ...
    ...    ${node}：zookeeper节点路径
    ...
    ...
    ...    示例：
    ...
    ...    | ${exist} | \ Zookeeper节点存在性 | 10.124.2.35:2181 | /migu/param/provStatus |
    Connect To Zookeeper    ${hosts}
    ${result}    Exists    ${node}
    Disconnect From Zookeeper
    [Return]    ${result}

内容校验模板
    [Arguments]    ${result}    @{args}
    [Documentation]    用于校验指定对象中是否包含某个或某几个字符串
    ...
    ...    入参说明：
    ...
    ...    ${result} ：待校验的对象
    ...
    ...    @{args}：字符串序列
    ...
    ...    示例：
    ...
    ...    | 内容校验模板 | ${responseData} | HTTP Status 500 - cannt parse request | Apache Tomcat/9.0.0 |
    : FOR    ${arg}    IN    @{args}
    \    Should Contain    ${result}    ${arg}

文件内容校验
    [Arguments]    ${host}    ${username}    ${passwd}    ${port}    ${file_path}    ${file_name}
    ...    @{content}
    [Documentation]    用于校验服务器上某个文件是否包含指定内容
    ...
    ...    入参说明：
    ...
    ...    ${host}：服务器IP地址
    ...
    ...    ${username}：服务器用户名
    ...
    ...    ${passwd}：服务器密码
    ...
    ...    ${port}：端口，ssh端口22，telnet端口23
    ...
    ...    ${file_path}：文件路径
    ...
    ...    ${file_name}：文件名
    ...
    ...    @{content}：待校验的文件内容
    ...
    ...    示例：
    ...
    ...    | 文件内容校验 | ${G_Host} | ${G_UserName} | ${G_Passwd} | ${G_SSHPort} | /home/migu/data/log | order.log | 123123122312312321345 |
    #获取文件内容
    ${file_content}    CommonLibrary Linux Server Operate    ${host}    ${username}    ${passwd}    ${port}    cd ${file_path};cat ${file_name};
    #校验文件内容
    : FOR    ${arg}    IN    @{content}
    \    Should Contain    ${file_content}[0]    ${arg}

替换配置文件
    [Arguments]    ${host}    ${username}    ${passwd}    ${port}    ${server_file_path}    ${local_file_path}
    ...    ${file_name}
    [Documentation]    用于替换服务器的某个配置文件。
    ...
    ...    入参说明：
    ...
    ...    ${host}：服务器IP地址，建议使用全局变量。
    ...
    ...    ${username}：服务器用户名，建议使用全局变量。
    ...
    ...    ${passwd}：服务器密码，建议使用全局变量。
    ...
    ...    ${port}：端口，建议使用全局变量。
    ...
    ...    ${server_file_path}：服务器文件路径，建议使用全局变量。
    ...
    ...    ${local_file_path}：本地文件路径。
    ...
    ...    ${file_name}：文件名称
    ...
    ...    @{command}：上传配置文件后，服务器执行的命令
    ...
    ...    上传本地自动化工程目录下的配置文件，服务器相应路径下的同名文件改名为xxx.bak，然后执行命令，使新的配置文件生效。
    ...
    ...    示例：
    ...
    ...    | 替换配置文件 | ${G_Host} | ${G_UserName} | ${G_Passwd} | ${G_SSHPort} | ${G_ServerFilePath} | ${G_Path}\\计费\\Resources | test.xml |
    #备份老配置文件
    CommonLibrary Linux Server Move File    ${host}    ${username}    ${passwd}    ${server_file_path}/${file_name}    ${server_file_path}/${file_name}.bak    ${port}
    #上传新配置文件
    CommonLibrary Linux Server Upload File    ${host}    ${username}    ${passwd}    ${server_file_path}/${file_name}    ${local_file_path}/${file_name}    ${port}

恢复配置文件
    [Arguments]    ${host}    ${username}    ${passwd}    ${port}    ${server_file_path}    ${file_name}
    [Documentation]    用于恢复服务器的配置文件。
    ...
    ...    入参说明：
    ...
    ...    ${G_Host}：服务器IP地址，建议使用全局变量。
    ...
    ...    ${G_UserName}：服务器用户名，建议使用全局变量。
    ...
    ...    ${G_Passwd}：服务器密码，建议使用全局变量。
    ...
    ...    ${G_SSHPort}：端口，建议使用全局变量。
    ...
    ...    ${G_ServerFilePath}：服务器文件路径，建议使用全局变量。
    ...
    ...    test.xml ：文件名称
    ...
    ...
    ...
    ...
    ...    示例：
    ...
    ...    | 恢复配置文件 | ${G_Host} | ${G_UserName} | ${G_Passwd} | ${G_SSHPort} | ${G_ServerFilePath} | test.xml |
    #删除新配置文件
    CommonLibrary Linux Server Delete File    ${host}    ${username}    ${passwd}    ${server_file_path}/${file_name}    ${port}
    #恢复老配置文件
    CommonLibrary Linux Server Move File    ${host}    ${username}    ${passwd}    ${server_file_path}/${file_name}.bak    ${server_file_path}/${file_name}    ${port}

配置文件生效
    [Arguments]    ${host}    ${username}    ${passwd}    ${port}    ${command}    ${expect}
    [Documentation]    用于替换配置文件后，服务器执行某个命令，使配置文件生效。
    ...
    ...    入参说明：
    ...
    ...    ${host}：服务器IP地址，建议使用全局变量。
    ...
    ...    ${username}：服务器用户名，建议使用全局变量。
    ...
    ...    ${passwd}：服务器密码，建议使用全局变量。
    ...
    ...    ${port}：端口，建议使用全局变量。
    ...
    ...    ${command}：上传配置文件后，为了使文件生效，服务器需要执行的命令。
    ...
    ...    ${expect}：服务器执行命令后，预期的返回结果。
    ...
    ...    示例：
    ...
    ...    | 配置文件生效 | ${G_Host} | ${G_UserName} | ${G_Passwd} | ${G_SSHPort} | cd /home/migu/user/chenm/loadfile2zk;java -cp /home1/migu/migu/libs/*:loadfile2zk.jar loadfile2zk.Loadfile2zk 10.25.212.22:2181 /migu/param/billing-month billing-month.xml | Success |
    #配置文件生效
    ${result}    CommonLibrary Linux Server Operate    ${host}    ${username}    ${passwd}    ${port}    ${command}
    Should Contain    @{result}[0]    ${expect}

构造预置数据模板
    [Arguments]    ${DBType}    ${DBConnStr}    ${RandomElement}
    [Documentation]    用于预置数据库测试数据，根据不同的业务场景，完成insert into语句的编写，需要将该关键字复制到对应中心的业务逻辑关键字中。如果insert into语句不需要使用随机数，删除出入参的${RandomElement}以及 #生成指定字段对应的随机数 部分即可。
    ...
    ...    入参说明：
    ...
    ...    ${DBType}：数据库类型，例如cx_Oracle、mysql
    ...
    ...    ${DBConnStr} ：数据库连接串，例如migu_jf/migu_jf@10.25.212.19:1521/orcl，建议使用全局变量
    ...
    ...    ${RandomElement}：后面的insert into语句中需要使用随机数替换的字段，使用字典格式，例如{"ORDER_ID":"00000-99999","ContentID":"00000-99999"}
    ...
    ...    返回值：
    ...
    ...    入参${RandomElement}中对应字段被替换为随机数后的json字符串，例如
    ...    {"ORDER_ID": 800542713, "ContentID" : 23432}
    ...
    ...    示例：
    ...
    ...    | ${randomvalue} | 构造预置数据模板 | cx_Oracle | ${G_DBConnStrMiguJF} | ${Random_Element} |
    ...
    ...    | ${req_data_list} | 获取请求报文 | ${Req_Data_File} | ${randomvalue} | Req_Data_001 |
    Connect To Database Using Custom Params    ${DBType}    ${DBConnStr}
    #生成指定字段对应的随机数
    ${RandomElement}    CommonLibrary JsonStr To Dic    ${RandomElement}
    @{keys}    Get Dictionary Keys    ${RandomElement}
    : FOR    ${key}    IN    @{keys}
    \    ${value}    Get From Dictionary    ${RandomElement}    ${key}
    \    ${start}    ${end}    Split String    ${value}    -
    \    ${randomvalue}    Evaluate    random.randint(${start}, ${end})    modules=random, sys
    \    ${randomvalue}    Convert To String    ${randomvalue}
    \    Set To Dictionary    ${RandomElement}    ${key}    ${randomvalue}
    #执行数据预置操作
    Execute Sql String    insert into TG_CDR_MONTH_HIS08 (ORDER_ID, TRADESESSION, PHONENUMBER, OPER_CODE, OPER_CHANNEL, OPER_TIME, EFFECT_TIME, SP_CODE, SP_SERV_CODE, CHANNEL_CODE, EXTEND_ATTR, AMOUNT, LAUNCH_TYPE, OLD_PHONENUMBER, BIZTYPE, BOSS_SEQ, REC_TIME, KAFKA_REC_TIME, MONTH_MSG_TYPE, COMPANY_MSG_TYPE, RESULT_CODE, RESULT_DESC, BATCH_ID, OPER_MONTH, RESERVED1, RESERVED2, RESERVED3, RESERVED4, RESERVED5, RESERVED6, RESERVED7, RESERVED8, RESERVED9, RESERVED10, RESERVED11, RESERVED12, RESERVED13, RESERVED14, RESERVED15, RESERVED16, RESERVED17, RESERVED18, RESERVED19) values (&{RandomElement}[ORDER_ID], '0238BIP5A13420170728100440480828', '13934919667', '01', '02', '20170728100440', '20170728100440', '698038', '80000000000100005937', '8800', 'testshaoyan0728', '600', '1', null, null, null, '20170728100440826', '20170728100441068', '01', '01', '4807', 'PROVICE SERVICE UNSUPPORTED', '9920170728100855000001', '07', '1', '20170728100855', '0', null, null, '0', '01', null, null, null, null, null, null, null, null, null, null, null, null)
    ${RandomElement}    CommonLibrary Dic To JsonStr    ${RandomElement}
    Disconnect From Database
    [Return]    ${RandomElement}

清理预置数据模板
    [Arguments]    ${DBType}    ${DBConnStr}    ${RandomElement}
    [Documentation]    用于清理数据库预置的测试数据，根据不同的业务场景，完成delete from语句的编写，需要将该关键字复制到对应中心的业务逻辑关键字中。如果预置的测试数据不涉及随机数，删除入参${RandomElement}即可。
    ...
    ...    入参说明：
    ...
    ...    ${DBType}：数据库类型，例如cx_Oracle、mysql
    ...
    ...    ${DBConnStr} ：数据库连接串，例如migu_jf/migu_jf@10.25.212.19:1521/orcl，建议使用全局变量
    ...
    ...    ${RandomElement}：delete from语句中需要使用随机数替换的字段，直接使用构造预置数据模板的返回值。
    ...
    ...    示例：
    ...
    ...    | ${randomvalue} | 构造预置数据模板 | cx_Oracle | ${G_DBConnStrMiguJF} | ${Random_Element} |
    ...
    ...    | 清理预置数据模板 | cx_Oracle | ${G_DBConnStrMiguJF} | ${randomvalue} |
    Connect To Database Using Custom Params    ${DBType}    ${DBConnStr}
    #将json串转化为字典
    ${RandomElement}    CommonLibrary JsonStr To Dic    ${RandomElement}
    #执行数据清理操作
    Execute Sql String    delete from TG_CDR_MONTH_HIS08 where ORDER_ID = '&{RandomElement}[ORDER_ID]'
    Disconnect From Database

环境清理
    [Documentation]    用于清理环境中的垃圾数据
    ...
    ...    入参说明：
    ...
    ...    用于测试用例结束后的环境清理操作，放在测试用例的teardown里，这里的步骤执行失败，不影响测试用例的执行结果。
    ...
    ...    包含断开数据库连接、清理测试数据、恢复测试环境等操作。
    ...
    ...
    ...    示例：
    ...
    ...    执行SQL语句 | DELETE FROM person_employee_table; | DELETE FROM person_table
    #断开数据库连接
    Run Keyword And Ignore Error    Disconnect From Database
    #其他

获取生效失效日期
    [Arguments]    ${createTime}    ${validFormat}    ${periodUnit}    ${n}=-1
    [Documentation]    获取生效和失效日期，即根据创建日期，生效方式，周期单位和周期数，计算出生效和失效日期：
    ...
    ...    入参说明：
    ...
    ...    createTime：为订单创建日期，手动输入日期字符串：格式为'YYYYMMDDHHMISS'
    ...
    ...    validFormat： 为生效方式的设置，分别：1为立即生效，2为次月生效
    ...
    ...    periodUnit： 为周期单位，分别有0 日，1 周，2 月，3 年
    ...
    ...    n：为周期数设置，默认为-1，永久生效
    ...
    ...    出参说明：
    ...
    ...    ${validate}:返回生效日期
    ...    ${expiredate}:返回失效日期
    ...
    ...    示例：
    ...    | ${validate} | ${expiredate} | 获取生效失效日期 | 20171101103240 | 1 | 2 | 1 |
    ${date}    CommonLibrary Get Valid Expire Date    ${createTime}    ${validFormat}    ${periodUnit}    ${n}
    [Return]    ${date}

获取文件总行数
    [Arguments]    ${host}    ${username}    ${passwd}    ${port}    ${file}
    [Documentation]    用于返回文件总记录数
    ...
    ...    入参说明：
    ...
    ...    ${host}：服务器IP地址
    ...
    ...    ${username}：服务器用户名
    ...
    ...    ${passwd}：服务器密码
    ...
    ...    ${port}：端口，ssh端口22，telnet端口23
    ...
    ...    ${file}：文件，使用绝对路径
    ...
    ...    出参说明：
    ...
    ...    ${totalcount}: 文件总行数
    ...
    ...
    ...    示例：
    ...
    ...    | ${totalcount} | 获取文件总行数 | ${G_Host} | ${G_UserName} | ${G_Passwd} | ${G_SSHPort} | /home/migujsj/apache-tomcat-8-monitor/logs/localhost_access_log.2017-12-03.txt |
    ${result}    CommonLibrary Linux Server Operate    ${host}    ${username}    ${passwd}    ${port}    awk 'END{print NR}' ${file}
    ${totalcount}    Set Variable    ${result[0]}
    [Return]    ${totalcount}

获取文件指定行内容
    [Arguments]    ${host}    ${username}    ${passwd}    ${port}    ${file}    ${start}
    ...    ${end}=$
    [Documentation]    用于截取指定行范围的文件内容
    ...
    ...    入参说明：
    ...
    ...    ${host}：服务器IP地址
    ...
    ...    ${username}：服务器用户名
    ...
    ...    ${passwd}：服务器密码
    ...
    ...    ${port}：端口，ssh端口22，telnet端口23
    ...
    ...    ${file}：文件，使用绝对路径
    ...
    ...    ${start}：开始行
    ...
    ...    ${end}：结束行
    ...
    ...    出参说明：
    ...
    ...    ${fileContent}: 截取的指定行范围的文件内容
    ...
    ...
    ...    示例：
    ...
    ...    | ${fileContent} | 获取文件指定行内容 | ${G_Host} | ${G_UserName} | ${G_Passwd} | ${G_SSHPort} | /home/migujsj/apache-tomcat-8-monitor/logs/server.log | 60 | 90 |
    ${result}    CommonLibrary Linux Server Operate    ${host}    ${username}    ${passwd}    ${port}    sed -n '${start},${end}p' ${file}
    ${fileContent}    Set Variable    ${result[0]}
    [Return]    ${fileContent}

数据库与文件内容比较
    [Arguments]    ${DBConnStr}    ${sqlStatement}    ${file_content}    ${DBType}=pymysql
    [Documentation]    用于校验数据库查询结果是否在文件内容中存在
    ...
    ...    入参说明：
    ...
    ...    ${DBConnStr}：数据库连接串，例如username/passwd@127.0.0.1:1521/orcl
    ...
    ...    ${sqlStatement}：要执行的SQL语句，例如DELETE FROM person_employee_table
    ...
    ...    ${file_content} 为文件内容
    ...
    ...    ${DBType}：数据库类型，默认值是cx_Oracle，也支持其他类型的数据库，例如mysql
    ...
    ...
    ...    示例：
    ...
    ...    数据库与文件内容比较 |${DBConnStr} | ${sqlStatement} | ${file_content} | ${DBType}=pymysql
    [Timeout]
    Connect To Database Using Custom Params    ${DBType}    ${DBConnStr}
    Execute Sql String    ${sqlStatement}
    ${db_result}    Query    ${sqlStatement}
    Compare DB with File    ${db_result}    ${file_content}
    Disconnect From Database
    [Teardown]

数据库与报文字段比对(单条)
    [Arguments]    ${DBConnStr}    ${QuerySql}    ${Message}    @{FieldList}
    [Documentation]    用于比对数据库查询结果的第一条记录与JSON报文的指定字段值是否一致。
    ...
    ...    入参说明：
    ...
    ...    ${DBConnStr}：数据库连接串
    ...
    ...    ${QuerySql}：数据库查询sql语句
    ...
    ...    ${Message}：JSON报文
    ...
    ...    @{FieldList}：报文字段序列
    ...
    ...    *注意* 数据库查询sql语句中的字段顺序要与@{FieldList}中的字段顺序保持一致
    ...
    ...    示例：
    ...
    ...    | 数据库与报文字段比对(单条) | ${G_mysql} | select content_Code,content_name,content_type,last_status_value from ct_info where content_code='${contentCode}' | ${responseData} | content/contentCode | content/name | content/contentType | content/statusValue |
    Connect To Database Using Custom Params    pymysql    ${DBConnStr}
    @{QueryResult}    Query    ${QuerySql}
    ${DBValue}    CommonLibrary Tuple To List    @{QueryResult}[0]
    Disconnect From Database
    ${message_dic}    To Json    ${Message}
    ${MsgValue}    Create List
    : FOR    ${field}    IN    @{FieldList}
    \    ${value}    Get Response Data Value Unicode    ${message_dic}    ${field}
    \    Append To List    ${MsgValue}    ${value}
    log    ${MsgValue}
    Should Be Equal As Strings    ${DBValue}    ${MsgValue}

数据库与报文字段比对(全部)
    [Arguments]    ${DBConnStr}    ${QuerySql}    ${Message}    ${Field}
    [Documentation]    用于比对数据库查询结果与JSON报文List类型的字段值是否一致。
    ...
    ...    入参说明：
    ...
    ...    ${DBConnStr}：数据库连接串
    ...
    ...    ${QuerySql}：数据库查询sql语句
    ...
    ...    ${Message}：JSON报文
    ...
    ...    ${Field}：报文字段名称，字段值为List
    ...
    ...    示例：
    ...
    ...    | 数据库与报文字段比对(全部) | ${G_mysql} | select content_id from ct_info where content_code='${contentCode}' | ${responseData} | content/contentid |
    Connect To Database Using Custom Params    pymysql    ${DBConnStr}
    @{QueryResult}    Query    ${QuerySql}
    Disconnect From Database
    log    ${QueryResult}
    ${message_dic}    To Json    ${Message}
    ${MsgValue}    Get Response Data Value    ${message_dic}    ${Field}
    log    ${MsgValue}
    Compare DB With List    ${QueryResult}    ${MsgValue}

数据库与XML报文字段比对(单条)
    [Arguments]    ${DBConnStr}    ${QuerySql}    ${Message}    @{FieldList}
    [Documentation]    用于比对数据库查询结果的第一条记录与XML报文的指定字段值是否一致。
    ...
    ...    入参说明：
    ...
    ...    ${DBConnStr}：数据库连接串
    ...
    ...    ${QuerySql}：数据库查询sql语句
    ...
    ...    ${Message}：XML格式的报文
    ...
    ...    @{FieldList}：报文字段序列
    ...
    ...    *注意* 数据库查询sql语句中的字段顺序要与@{FieldList}中的字段顺序保持一致
    ...
    ...    示例：
    ...
    ...    | 数据库与XML报文字段比对(单条) | ${G_mysql} | select content_Code,content_name,content_type,last_status_value from ct_info where content_code='${contentCode}' | ${responseData} | content/contentCode | content/name | content/contentType | content/statusValue |
    Connect To Database Using Custom Params    pymysql    ${DBConnStr}
    @{QueryResult}    Query    ${QuerySql}
    ${DBValue}    CommonLibrary Tuple To List    @{QueryResult}[0]
    Disconnect From Database
    ${MsgValue}    Create List
    : FOR    ${field}    IN    @{FieldList}
    \    ${value}    Get Response Data Value    ${Message}    ${field}    xml
    \    ${value}    Run Keyword If    '${value}' == 'None'    Set Variable    None
    \    ...    ELSE    Set Variable    ${value}
    \    Append To List    ${MsgValue}    ${value}
    log    ${MsgValue}
    Should Be Equal As Strings    ${DBValue}    ${MsgValue}

数据库与报文字段比对(多字段组合)
    [Arguments]    ${DBConnStr}    ${QuerySql}    ${Split}    ${Message}    @{FieldList}
    [Documentation]    用于比对数据库查询结果(注意：数据库结果形式为一个表字段数值由多个报文字段值组合而成，如：8821116109#660000000073753380661518#22211585)与JSON报文的指定字段值是否一致。
    ...
    ...    入参说明：
    ...
    ...    ${DBConnStr}：数据库连接串
    ...
    ...    ${QuerySql}：数据库查询sql语句
    ...
    ...    ${Split}: 分割符，如：\#，用于将数据库返回结果值，进行按照#进行分割数据值
    ...
    ...    ${Message}：JSON报文
    ...
    ...    @{FieldList}：报文字段序列
    ...
    ...    *注意* 数据库查询sql语句中的字段顺序要与@{FieldList}中的字段顺序保持一致
    ...
    ...    示例：
    ...
    ...    | 数据库与报文字段比对(多字段组合) | ${G_mysql} | select content_Code,content_name,content_type,last_status_value from ct_info where content_code='${contentCode}' | \# | ${responseData} | content/contentCode | content/name | content/contentType | content/statusValue |
    Connect To Database Using Custom Params    pymysql    ${DBConnStr}
    @{QueryResult}    Query    ${QuerySql}
    log    @{QueryResult}
    ${DBValue}    CommonLibrary Tuple To List    @{QueryResult}[0]
    Disconnect From Database
    ${DBValue_list}    Create List
    : FOR    ${db_value}    IN    @{DBValue}
    \    ${db_value_split}    Split String    ${db_value}    ${Split}
    \    Append To List    ${DBValue_list}    @{db_value_split}
    log    ${DBValue_list}
    ${message_dic}    To Json    ${Message}
    ${MsgValue}    Create List
    : FOR    ${field}    IN    @{FieldList}
    \    ${value}    Get Response Data Value    ${message_dic}    ${field}
    \    ${value}    Convert To String    ${value}
    \    Append To List    ${MsgValue}    ${value}
    log    ${MsgValue}
    Should Be Equal As Strings    ${DBValue_list}    ${MsgValue}

数据库清理
    [Arguments]    ${DBConnStr}    ${DBType}=cx_Oracle    @{sqlStatement}
    [Documentation]    用于清理数据库垃圾数据。
    ...
    ...    入参说明：
    ...
    ...    ${DBConnStr}：数据库连接串信息
    ...
    ...    ${DBType}：数据库类型，例如cx_Oracle、pymysql
    ...
    ...    @{sqlStatement}：清理SQL语句，支持多个。
    ...
    ...    示例：
    ...
    ...    | 数据库清理 | ${G_DBConnStrMiguJSJ} | cx_Oracle | delete from TD_BU_CPINFO t1 where t1.SEND_AQGK_TAG = 2 and t1.subcpcode = '010' and t1.cooperatecode = '${CooperateCode}' | delete from TD_BU_CPINFO_MOD t1 where t1.subcpcode = '010' and t1.cooperatecode = '${CooperateCode}' |
    Connect To Database Using Custom Params    ${DBType}    ${DBConnStr}
    : FOR    ${sql}    IN    @{sqlStatement}
    \    Execute Sql String    ${sql}
    Disconnect From Database

替换报文数据
    [Arguments]    ${request_data}    ${replace_data}
    [Documentation]    用于替换报文中的指定数据
    ...
    ...    入参说明：
    ...
    ...    @{req_data_list}[0]，获取报文
    ...
    ...
    ...    出参说明：
    ...
    ...    ${replace_data_list}，替换报文中的userid和producrinsid的值
    ...
    ...
    ...
    ...    示例：
    ...
    ...    ${replace_data} | 替换报文数据 | @{req_data_list}[0] \ |{"userId":"${userId}","productInsId":"${productInsId}"}|
    ${replace_data}    Replace Request Data    ${request_data}    ${replace_data}
    [Return]    ${replace_data}

查询数据库
    [Arguments]    ${DBConnStr}    ${sqlStatement}    ${DBType}=pymysql
    [Documentation]    用于查询数据库，并返回查询结果。
    ...
    ...    入参说明：
    ...
    ...    ${DBConnStr}：数据库连接串
    ...
    ...    ${sqlStatement}：数据库查询SQL
    ...
    ...    ${DBType}：数据库类型，例如cx_Oracle、pymysql
    ...
    ...    出参说明：
    ...
    ...    ${result}：数据库查询结果
    ...
    ...    示例：
    ...
    ...    | ${result} | 查询数据库 | ${DBConnStr} | ${sqlStatement} | ${DBType} |
    Connect To Database Using Custom Params    ${DBType}    ${DBConnStr}
    ${result}    Query    ${sqlStatement}
    Disconnect From Database
    [Return]    ${result}

LDAP新增
    [Arguments]    ${ldapIP}    ${port}    ${bind_name}    ${bind_passwd}    ${addDN}    ${username}
    ...    ${pwd}
    [Documentation]    发送ldap新增请求：
    ...
    ...    入参说明：
    ...
    ...    ${ldapIP}：为服务器ip
    ...
    ...    ${port}：服务器端口
    ...
    ...    ${bind_name}：用户名
    ...
    ...    ${bind_passwd}：密码
    ...
    ...    ${addDN}：新增的账户的DN
    ...
    ...    ${username}：新增账户的username
    ...
    ...    ${pwd}：新增账户的密码
    ...
    ...
    ...    示例：
    ...    | 结果 | 方法名称 | 服务器地址 | port| bind_name |bind_passwd|addDN|username|pwd
    ...    | ${result}= | ladpadd | 10.124.2.216 | 2389 | cn=admin,dc=migu,dc=cn|2389 |uid=caojun1304,ou=migu.Inc,dc=migu,dc=cn|caojun1304|1234567
    ${result}    ldapadd    ${ldapIP}    ${port}    ${bind_name}    ${bind_passwd}    ${addDN}
    ...    ${username}    ${pwd}
    [Return]    ${result}

LDAP删除
    [Arguments]    ${ldapIP}    ${port}    ${bind_name}    ${bind_passwd}    ${deleteDN}
    [Documentation]    发送ldap删除请求：
    ...
    ...    入参说明：
    ...
    ...    ${ldapIP}：服务器ip
    ...
    ...    ${port}：端口号
    ...
    ...    ${bind_name}：用户名
    ...
    ...    ${bind_passwd}：密码
    ...
    ...    ${deleteDN}：删除账户的DN
    ...
    ...    示例：
    ...
    ...    | 结果 | 方法名称 | 服务器地址 | 端口 | bind_name |bind_passwd|deleteDN
    ...    | ${result}= | ladpserch | 10.124.2.216 | 3389 | cn=admin,dc=migu,dc=cn | Ta6G@pL0 |uid=caojun01,ou=migu.Inc,dc=migu,dc=cn
    [Timeout]
    ${result}    ldapdelete    ${ldapIP}    ${port}    ${bind_name}    ${bind_passwd}    ${deleteDN}
    [Return]    {result}

LDAP查询
    [Arguments]    ${ldapIP}    ${port}    ${baseDN}    ${searchFilter}
    [Documentation]    发送ldap查询请求：
    ...
    ...
    ...    入参说明：
    ...
    ...    ${ldapIP}:为服务器ip
    ...
    ...    ${port}:为端口号
    ...
    ...    ${baseDN}:为查询范围
    ...
    ...    ${searchFilter}为查询过滤条件
    ...
    ...    示例：
    ...
    ...    | 结果 | 方法名称 | 服务器地址| port |查询范围 \ | 查询过滤条件|
    ...    | ${result}= | ladpserch | 10.124.2.216 | \ 3389| dc=migu,dc=cn | uid=*test* |
    ${result}    Ldapserch    ${ldapIP}    ${port}    ${baseDN}    ${searchFilter}
    [Return]    ${result}

LDAP修改
    [Arguments]    ${ldapIP}    ${port}    ${bind_name}    ${bind_passwd}    ${dn}    @{attr_list1}
    [Documentation]    发送ldap修改请求：
    ...
    ...    入参说明：
    ...
    ...    ${ldapIP}：为服务器ip
    ...
    ...    ${port}：服务器端口
    ...
    ...    ${bind_name}：用户名
    ...
    ...    ${bind_passwd}：密码
    ...
    ...    ${DN}：修改的账户的DN
    ...
    ...    ${attr_list1}：修改的条件list
    ...
    ...
    ...    示例：
    ...    | 结果 | 方法名称 | 服务器地址 | port| bind_name |bind_passwd|DN|attr_list
    ...    | ${result}= | ladpadd | 10.124.2.216 | 2389 | cn=admin,dc=migu,dc=cn|2389 |uid=caojun,ou=migu.Inc,dc=migu,dc=cn|(ldap.MOD_DELETE,),('givenName'),('123')
    ...
    ...
    ...
    ...    修改支持三种方式：
    ...    MOD_ADD: 如果属性存在，这个属性可以有多个值，那么新值加进去，旧值保留
    ...    MOD_DELETE ：如果属性的值存在，值将被删除
    ...    MOD_REPLACE ：这个属性所有的旧值将会被删除，这个值被加进去
    [Timeout]
    ${result}    Ldapmodify    ${ldapIP}    ${port}    ${bind_name}    ${bind_passwd}    ${dn}
    ...    @{attr_list1}
    [Return]    ${result}

获取异常参数
    [Arguments]    ${file}    ${row}
    [Documentation]    用于从 接口名.error 文件中获取指定行的内容，该关键字和更新报文数据关键字结合使用，用于一个脚本执行所有字段异常校验的场景。
    ...    接口名.error 文件的每一行都包含三列，第一列指定需要更新的报文字段信息，使用英文逗号隔开，第二列指定该场景的错误码，第三列指定错误描述。三列之间使用tab键隔开。
    ...
    ...    示例：
    ...    人物搜索接口.error文件的某一行：
    ...    $.appId:100,$.msisdn:15850790808 1000001 appId不能为空
    ...
    ...    $.appId:100含义说明：需要将报文中的appId字段值替换为100，$表示根节点。
    ...
    ...    入参说明：
    ...
    ...    ${file}：文件名，推荐直接使用${Req_Data_File}变量
    ...
    ...    ${row}：文件指定行
    ...
    ...    出参说明：
    ...
    ...    @{content}：返回内容包括：需要替换的报文字段信息、错误码、错误提示
    ...
    ...    示例：
    ...
    ...    | ${fields} | ${errcode} | ${errmsg} | 获取异常参数 | ${Req_Data_File} | 2 |
    ...
    ...    一个脚本执行所有字段异常校验示例：
    ...
    ...    | ${requestDataList} | ${randomElementValue} | 获取请求报文 | ${Req_Data_File} | ${Random_Element} | Req_Data_001 |
    ...    | :FOR | ${i} | IN RANGE | 2 | 5 |
    ...    | | ${fields} | ${errcode} | ${errmsg} | 获取异常参数 | ${Req_Data_File} | ${i} |
    ...    | | ${requestData} | 更新报文数据 | ${requestDataList[0]} | ${fields} |
    ...    | | ${response} | 发送Post请求 | ${url} | /bcse_video_spyy/miguvideo/search/getPerson | headers=&{Headers} | data=${requestData} |
    ...    | | 内容校验模板 | ${response} | ${errcode} | ${errmsg} |
    ${filename}    CommonLibrary_get_filename    ${file}
    ${rownum}    Evaluate    ${row}-1
    ${line}    CommonLibrary_read_file_line    ${filename}.error    ${rownum}
    ${line}    Strip String    ${line}
    @{content}    Split String    ${line}    \t
    [Return]    @{content}

参数和返回码校验(Post)
    [Arguments]    ${Req_Data_File}    ${requestData}    ${URL}    ${URI}    &{Headers}
    [Documentation]    根据接口名.error文件的配置，自动进行响应结果的校验，请求类型为post。
    ...
    ...    接口名.error 文件的每一行至少包含两列，第一列指定需要更新的报文字段信息，
    ...    多个字段值使用英文逗号隔开，第二列到最后一列指定该场景下，响应报文需要校验的内容，
    ...    例如错误码、错误描述等。列与列之间使用tab键隔开。
    ...
    ...    例如：
    ...
    ...    $.appId:100,$.msisdn:15850790808 1000001 appId不能为空
    ...
    ...    $.appId:100含义说明：需要将报文中的appId字段值替换为100，$表示根节点。
    ...
    ...    参数说明：
    ...
    ...    ${Req_Data_File}：配置文件名称，直接使用测试套的${Req_Data_File}变量。
    ...
    ...    ${requestData}：从配置文件获取到的某条报文。
    ...
    ...    ${URL}：被测系统URL地址
    ...
    ...    ${URI}：接口URI
    ...
    ...    &{Headers}：报文头
    ...
    ...    示例：
    ...
    ...    | ${requestDataList} | ${randomElementValue} | 获取请求报文 | ${Req_Data_File} | {Random_Element} | Req_Data_040 |
    ...    | 参数和返回码校验(Post) | ${Req_Data_File} | ${requestDataList[0]} | ${url} | /bcse_video_spyy/miguvideo/search/getPerson | &{Headers} |
    ${failcount}    Set Variable    0
    ${filename}    CommonLibrary_get_filename    ${Req_Data_File}
    ${rowcount}    CommonLibrary_get_file_rowcount    ${filename}.error
    : FOR    ${i}    IN RANGE    0    ${rowcount}
    \    @{content}    获取异常参数    ${Req_Data_File}    ${i}
    \    ${Data}    更新报文数据    ${requestData}    @{content}[0]
    \    ${response}    发送Post请求    ${URL}    ${URI}    headers=&{Headers}    data=${Data}
    \    ${response1}    Decode Bytes To String    ${response}    UTF-8
    \    ${status}    Run Keyword And Return Status    内容校验模板    ${response1}    @{content[1:]}
    \    ${failcount}    Run Keyword If    ${status}==False    Evaluate    ${failcount}+1
    \    ...    ELSE    Set Variable    ${failcount}
    \    Run Keyword If    ${status}==False    log    结果校验失败    ERROR
    Run Keyword If    ${failcount}!=0    log    结果校验失败${failcount}次
    Should Be Equal As Strings    结果校验失败${failcount}次    结果校验失败0次

参数和返回码校验(Get)
    [Arguments]    ${Req_Data_File}    ${requestData}    ${URL}    ${URI}    &{Headers}
    [Documentation]    根据接口名.error文件的配置，自动进行响应结果的校验，请求类型为get。
    ...
    ...    接口名.error 文件的每一行至少包含两列，第一列指定需要更新的报文字段信息，
    ...    多个字段值使用英文逗号隔开，第二列到最后一列指定该场景下，响应报文需要校验的内容，
    ...    例如错误码、错误描述等。列与列之间使用tab键隔开。
    ...
    ...    例如：
    ...
    ...    $.appId:100,$.msisdn:15850790808 1000001 appId不能为空
    ...
    ...    $.appId:100含义说明：需要将报文中的appId字段值替换为100，$表示根节点。
    ...
    ...    参数说明：
    ...
    ...    ${Req_Data_File}：配置文件名称，直接使用测试套的${Req_Data_File}变量。
    ...
    ...    ${requestData}：从配置文件获取到的某条报文。
    ...
    ...    ${URL}：被测系统URL地址
    ...
    ...    ${URI}：接口URI
    ...
    ...    &{Headers}：报文头
    ...
    ...    示例：
    ...
    ...    | ${requestDataList} | ${randomElementValue} | 获取请求报文 | ${Req_Data_File} | {Random_Element} | Req_Data_040 |
    ...    | 参数和返回码校验(Get) | ${Req_Data_File} | ${requestDataList[0]} | ${url} | /bcse_video_spyy/miguvideo/search/getPerson | &{Headers} |
    ${failcount}    Set Variable    0
    ${filename}    CommonLibrary_get_filename    ${Req_Data_File}
    ${rowcount}    CommonLibrary_get_file_rowcount    ${filename}.error
    : FOR    ${i}    IN RANGE    0    ${rowcount}
    \    @{content}    获取异常参数    ${Req_Data_File}    ${i}
    \    ${Data}    更新报文数据    ${requestData}    @{content}[0]
    \    ${response}    发送Get请求    ${URL}    ${URI}    params=${Data}    headers=&{Headers}
    \    ${status}    Run Keyword And Return Status    内容校验模板    ${response}    @{content[1:]}
    \    ${failcount}    Run Keyword If    ${status}==False    Evaluate    ${failcount}+1
    \    ...    ELSE    Set Variable    ${failcount}
    \    Run Keyword If    ${status}==False    log    结果校验失败    ERROR
    Run Keyword If    ${failcount}!=0    log    结果校验失败${failcount}次
    Should Be Equal As Strings    结果校验失败${failcount}次    结果校验失败0次

assert_dict_values
    [Arguments]    ${expectValue}    ${DBValue}
    [Documentation]    用于断言数据库字段返回的list结果。
    ...
    ...    入参说明：
    ...
    ...    ${expectValues} ：预期结果list，例如: {"a":"a","b":1}
    ...
    ...    ${DBValues}：执行sql查询出来的结果，例如：{"a":"a","b":1}
    ...
    ...    出参说明：结果校验断言
    ...
    ...    示例：
    ...
    ...    | assert_dict_values | \ {"a":"a","b":1} | {"a":"a","b":1} |
    ${keys}    Get Dictionary Keys    ${expectValue}
    : FOR    ${key}    IN    @{keys}
    \    ${result_expect_value}    Get From Dictionary    ${expectValue}    ${key}
    \    ${result_db_value}    Get From Dictionary    ${DBValue}    ${key}
    \    Should Be Equal As Strings    ${result_expect_value}    ${result_db_value}

assert_list_dict_values
    [Arguments]    ${expectValues}    ${DBValues}
    [Documentation]    用于断言数据库字段返回的list结果。
    ...
    ...    入参说明：
    ...
    ...    ${expectValues} ：预期结果list，例如: [{"a":"a","b":1}]
    ...
    ...    ${DBValues}：执行sql查询出来的结果集，例如：[{"a":"a","b":1}]
    ...
    ...    出参说明：结果校验断言
    ...
    ...    示例：
    ...
    ...    | assert_db_list_values | \ [{"a":"a","b":1}] | [{"a":"a","b":1}] |
    : FOR    ${index}    ${expectValue}    IN ENUMERATE    @{expectValues}
    \    ${DBValue}=    Set Variable    ${DBValues[${index}]}
    \    assert_dict_values    ${expectValue}    ${DBValue}

数据库校验
    [Arguments]    ${DBConnStr}    ${sqlStatement}    ${DBType}=pymysql    ${returnAsDict}=${False}    ${sansTran}=${False}
    [Documentation]    用于数据库校验，默认是Oracle数据库
    ...
    ...    入参说明：
    ...
    ...    ${DBConnStr}：数据库连接串，例如username/passwd@127.0.0.1:1521/oracle
    ...
    ...    ${sqlStatement}：数据库查询SQL语句及预期结果，字典格式，例如
    ...
    ...    {"select t1.contentid from TG_FULL_CHARGE_TMP t1 where order_id = '8739619410065812898203' union all select t2.contentid from TG_FULL_CHARGE_his_07 t2 where order_id = '8739619410065812898203'":"[]"} 表示预期查询结果为空
    ...
    ...    {"select t1.contentid from TG_FULL_CHARGE_TMP t1 where order_id = '8739619410065812898203' union all select t2.contentid from TG_FULL_CHARGE_his_07 t2 where order_id = '8739619410065812898203'":"[('30018283746272737646',)]"} 表示预期查询结果非空，需要注意的地方：如果只查询一个字段，预期结果里要在字段值后加上逗号。
    ...
    ...    同时也支持两个sql查询语句的结果做比较，例如
    ...
    ...    {"select t1.contentid from TG_FULL_CHARGE_TMP t1 where order_id = '0001707030956387995799'":"select t2.contentid from TG_FULL_CHARGE_his_07 t2 where order_id = '0001707030956387995888'"}
    ...
    ...    ${DBType}：数据库类型，默认值是cx_Oracle，也支持其他类型的数据库，例如mysql
    ...
    ...    示例：
    ...
    ...    | 数据库校验 | ${DBConnStr} | ${sqlStatement} | mysql |
    ...
    ...    | 数据库校验 | ${DBConnStr} | ${sqlStatement} |
    Connect To Database Using Custom Params    ${DBType}    ${DBConnStr}
    ${sqlStatement}    CommonLibrary JsonStr To Dic    ${sqlStatement}
    ${keys}    Get Dictionary Keys    ${sqlStatement}
    : FOR    ${sql}    IN    @{keys}
    \    ${expect}    Get From Dictionary    ${sqlStatement}    ${sql}
    \    ${DBValue}    Query    ${sql}    ${sansTran}    ${returnAsDict}
    \    #如果expect是SQL语句,则把expect的执行结果赋值给expectvalue
    \    ${yesOrNo}    Run Keyword And Return Status    Should Match Regexp    ${expect}    (?i)select.*from.*
    \    ${expectValue}=    Run Keyword IF    ${yesOrNo}    Query    ${expect}    ${sansTran}
    \    ...    ${returnAsDict}
    \    ...    ELSE    Set Variable    ${expect}
    \    Run Keyword IF    ${returnAsDict}    assert_list_dict_values    ${expectValue}    ${DBValue}
    \    Run Keyword Unless    ${returnAsDict}    Should Be Equal As Strings    ${expectValue}    ${DBValue}
    \    Log    ExpectValue is the same with DB QueryValue
    Disconnect From Database

数据库动态校验
    [Arguments]    ${DBConnStr}    ${sqlStatement}    ${retry}=3 times    ${interval}=10s    ${DBType}=pymysql    ${returnAsDict}=${False}
    [Documentation]    数据库动态校验，用于数据入库时间不定或数据库生效有时延，需要多次重复查询的场景。
    ...
    ...    入参说明：
    ...
    ...    ${DBConnStr}：数据库连接串，例如username/passwd@127.0.0.1:1521/oracle
    ...
    ...    ${sqlStatement}：数据库查询SQL语句及预期结果，字典格式，例如
    ...
    ...    {"select t1.contentid from TG_FULL_CHARGE_TMP t1 where order_id = '8739619410065812898203' union all select t2.contentid from TG_FULL_CHARGE_his_07 t2 where order_id = '8739619410065812898203'":"[('30018283746272737646',)]"}
    ...
    ...    ${retry}：可以设定为超时时长或重试次数，例如5 min或10 times
    ...
    ...    ${interval}：重试间隔，例如30s
    ...
    ...    ${DBType}：数据库类型，默认值是cx_Oracle，也支持其他类型的数据库，例如mysql
    ...
    ...    出参说明：结果校验断言
    ...
    ...    示例：
    ...
    ...    | 数据库动态校验 | ${G_DBConnStrMiguJF} | {"select t1.contentid from TG_FULL_CHARGE_TMP t1 where order_id = '0001707031000137995808' union all select t2.contentid from TG_FULL_CHARGE_his_07 t2 where order_id = '0001707031000137995808'":"[('3000000000060855997')]"} | 6 min | 30s |
    BuiltIn.Pass Execution If    '''${sqlStatement}'''=='''${None}'''    sqlStatement is None
    Wait Until Keyword Succeeds    ${retry}    ${interval}    数据库校验    ${DBConnStr}    ${sqlStatement}    ${DBType}
    ...    ${returnAsDict}
    Comment    CommonLibrary DB Dynamic Verify    ${DBConnStr}    ${sqlStatement}    ${retry}    ${interval}    ${DBType}

获取Jsonpath的值
    [Arguments]    ${responseData}    ${jsonpath}
    [Documentation]    用于从JSON格式的字符串里获取指定jsonpath的值。
    ...
    ...    入参说明：
    ...
    ...    ${responseData}：报文内容
    ...
    ...    ${jsonpatht}：JsonPath语法写的节点路径，如$.playRate
    ...
    ...    出参说明：
    ...
    ...    ${elementValue}：jsopath的值
    ...
    ...    示例：
    ...
    ...    | {value} | 获取Jsonpath的值 | ${responseData} | $.playRatePlanList[0].rateFee |
    ...    | log | ${value}|
    ${type}    Get Type    ${responseData}
    ${responseDict}    Run Keyword If    '''${type}'''=='''dict'''    Set Variable    ${responseData}
    ...    ELSE    Json To Dict    ${responseData}
    ${element}    Get Value From Json    ${responseDict}    ${jsonpath}
    ${elementValue}    Run Keyword If    ${element}    Set Variable    ${element[0]}
    ...    ELSE    Set Variable    ${None}
    [Return]    ${elementValue}

获取字符串中的RF变量名称
    [Arguments]    ${soure_str}
    [Documentation]    用于从原始字符串中获取有变量名称字符串
    ...
    ...    入参说明：
    ...
    ...    ${source_str}：原始字符串
    ...
    ...    出参说明：
    ...
    ...    ${var_names}：返回匹配到的变量名称字符串数字，匹配不到返回[]，
    ...
    ...    示例：
    ...
    ...    | ${var_names} | 获取字符串中的RF变量名称 | ‘’‘asdada${source_str}’‘’ |
    ${soure_str}    Convert To String    ${soure_str}
    ${var_names}    Get Regexp Matches    ${soure_str}    [$@&]{[a-zA-Z_]+[\w]*}
    [Return]    ${var_names}

全局变量替换
    [Arguments]    ${source_content}
    [Documentation]    用于将请求报文中包含变量名字符串转换成对应变量的值
    ...
    ...    入参说明：
    ...
    ...    ${source_content}：原始字典
    ...
    ...    出参说明：
    ...
    ...    ${source_content}：转换后的字典，
    ...
    ...    示例：
    ...
    ...    | ${result_content} | 全局变量替换 | ${source_contrunent} |
    ${is_json}    Run Keyword If    '''${source_content}'''.startswith('{') and '''${source_content}'''.endswith('}')    Set Variable    ${True}
    ...    ELSE    Set Variable    ${False}
    log    ${is_json}
    ${source_content}    Run Keyword If    ${is_json}    请求报文dict_变量名字符串转换成对应变量的值    ${source_content}
    ...    ELSE    请求报文str(xml)_变量名字符串转换成对应变量的值    ${source_content}
    [Return]    ${source_content}

将字符串中的变量名称替换成变量值
    [Arguments]    ${source_str}    ${var_names}
    [Documentation]    将字符串中的变量名称替换成变量值
    ...
    ...    入参说明：
    ...
    ...    ${source_str}：原始字符串
    ...
    ...    ${var_names}：变量名称列表
    ...
    ...    出参说明：
    ...
    ...    ${source_str}：转换后的字符串
    ...
    ...    示例：
    ...
    ...    | ${result_tr} | 将字符串中的变餇ХЍ称替换成变量值 | ${source_str} | ${var_names} |
    @{var_names}    Set Variable    ${var_names}
    : FOR    ${index}    ${var_name}    IN ENUMERATE    @{var_names}
    \    ${var_value}    Get Variable Value    ${var_name}
    \    ${source_str}    Replace String    ${source_str}    ${var_name}    ${var_value}
    [Return]    ${source_str}

请求报文dict_变量名字符串转换成对应变量的值
    [Arguments]    ${source_dict}
    [Documentation]    用于将字典中key或者value包含变量名字符串转换成对应变量的值
    ...
    ...    入参说明：
    ...
    ...    ${source_dict}：原始字典
    ...
    ...    出参说明：
    ...
    ...    ${source_dict}：转换后的字典，
    ...
    ...    示例：
    ...
    ...    | ${result_dict} | 全局变量替换 | ${source_dict} |
    @{items}    Get Dictionary Items    ${source_dict}
    : FOR    ${key}    ${value}    IN    @{items}
    \    ${source_key}    Set Variable    ${key}
    \    ${source_value}    Set Variable    ${value}
    \    ${tmp_key}    获取字符串中的RF变量名称    ${source_key}
    \    ${final_key}    Run Keyword If    ${tmp_key}    将字符串中的变量名称替换成变量值    ${source_key}    ${tmp_key}
    \    ...    ELSE    Set Variable    ${key}
    \    ${tmp_value}    获取字符串中的RF变量名称    ${source_value}
    \    ${final_value}    Run Keyword If    ${tmp_value}    将字符串中的变量名称替换成变量值    ${source_value}    ${tmp_value}
    \    ...    ELSE    Set Variable    ${value}
    \    Remove From Dictionary    ${source_dict}    ${key}
    \    Set To Dictionary    ${source_dict}    ${final_key}=${final_value}
    [Return]    ${source_dict}

请求报文str(xml)_变量名字符串转换成对应变量的值
    [Arguments]    ${source_str}
    [Documentation]    用于将字符串中包含变量名字符串转换成对应变量的值
    ...
    ...    入参说明：
    ...
    ...    ${source_str}：原始字典
    ...
    ...    出参说明：
    ...
    ...    ${source_str}：转换后的字典，
    ...
    ...    示例：
    ...
    ...    | ${result_str} | 全局变量替换 | ${source_str} |
    ${var_names}    获取字符串中的RF变量名称    ${source_str}
    ${source_str}    将字符串中的变量名称替换成变量值    ${source_str}    ${var_names}
    [Return]    ${source_str}


随机赋值变量
    [Arguments]    ${var_name}
    [Documentation]    此关键字用于为指定变量名随机赋值一个长度为 10 的由数字和字母组成的字符串。
    ...
    ...    入参说明：
    ...
    ...    ${var_name}: 要赋值的变量名，以字符串形式传入。
    ...
    ...    示例:
    ...
    ...    | 随机赋值变量 | my_variable |
    ...    | Log | 赋值后的变量值为: ${my_variable} |
    ${random_value}=    Evaluate    ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(10))    modules=random,string
    Set Test Variable    ${${var_name}}    ${random_value}